package _defer

import "fmt"

/**
什么是 defer？
 defer 语句的用途是：含有 defer 语句的函数，会在该函数将要返回之前，调用另一个函数。
*/

func Test() {

	// 示例1 使用 defer
	case1()

	// 示例2 延迟方法
	case2()

	// 示例3 延迟方法-实参取值
	case3()

	// 示例4 defer栈
	case4()

	// 使用defer 场景： 1.读取文件后关闭方法可以用到。2.记录方法执行完成返回值。等...

}

// 示例1 使用 defer
func case1() {
	arr1 := []int{1, 3, 2, 8, 4, 9}
	getMaxVal(arr1)
}

// 获取最大值函数
func getMaxVal(nums []int) {

	// 🔥使用defer 语法, 当执行完getMaxVal() 后才会执行print();  至于在那个位置声明defer 他都会等当前函数执行完，才会执行defer
	defer print()

	if nums == nil || len(nums) == 0 {
		fmt.Println("参数为空或未初始化...")
	}
	maxNum := nums[0]
	for _, v := range nums {
		if v > maxNum {
			maxNum = v
		}
	}
	fmt.Println("获取数组最大值，", maxNum)

}

func print() {
	fmt.Println("print() 打印。。。")
}

// 示例2 延迟方法
func case2() {
	p1 := person{"王卡", 23}
	defer p1.gainName()
	fmt.Println("case2() end ....")
}

type person struct {
	name string
	age  int
}

func (p person) gainName() {
	fmt.Println("获取person 名称， ", p.name)
}

// 示例3 延迟方法-实参取值
func case3() {
	var num1 int = 45
	defer printA(num1) // 这里延迟，获取的值是45🔥
	num1 = 100
	fmt.Println("num1 = ", num1)
}

func printA(num int) {
	fmt.Println("打印延迟方法-实参取值，", num)
}

// 示例4 defer栈
// 当一个函数内多次调用 defer时，Go 会把defer 调用放入到一个栈中，随后按照后进先出（Last In First Out, LIFO）的顺序执行
func case4() {
	str1 := "hello world!"
	fmt.Printf("打印参数str1: %s \n", string(str1))
	// 循环打印字符串中的字符
	for _, v := range []rune(str1) {
		fmt.Printf("%c  ", v)
	}
	fmt.Println()

	fmt.Println("使用defer 栈 循环打印字符串中的字符")
	for _, v := range []rune(str1) {
		defer fmt.Printf("%c  ", v)
	}
	fmt.Println()
}
